package chat

import (
	"fmt"
	netpack "im/im_server/proto"

	"google.golang.org/protobuf/proto"
)

type Handler func(proto.Message, *Connection) error

func NewPlayer() *Player {
	player := &Player{
		PlayerId:        -1,
		handlerCallback: make(map[netpack.MessageID]Handler),
	}
	player.PlayerId = -1
	return player
}

func (p *Player) registerMessage(s *ChatServer) {
	chatMessage := &ChatMessageLogic{}
	chatMessage.chatServer = s
	chatMessage.redisCmd = s.redisCmd

	createRoomMessage := &CreateRoomMessageLogic{}
	createRoomMessage.chatServer = s
	createRoomMessage.redisCmd = s.redisCmd

	joinRoomMessage := &JoinRoomMessageLogic{}
	joinRoomMessage.chatServer = s
	joinRoomMessage.redisCmd = s.redisCmd

	loginMessage := &LoginMessageLogic{}
	loginMessage.chatServer = s
	loginMessage.redisCmd = s.redisCmd

	p.handlerCallback[netpack.MessageID_CS_LOGIN] = loginMessage.Login
	p.handlerCallback[netpack.MessageID_CS_CHAT] = chatMessage.Chat
	p.handlerCallback[netpack.MessageID_CS_CREATE_CHATROOM] = createRoomMessage.CreateChatRoom
	p.handlerCallback[netpack.MessageID_CS_JOIN_CHATROOM] = joinRoomMessage.JoinChatRoom
}

type Player struct {
	handlerCallback map[netpack.MessageID]Handler
	PlayerId        int64
}

func (p *Player) isLogin() bool {
	return p.PlayerId > 0
}

func (p *Player) getHandlerCallback(id netpack.MessageID) (Handler, error) {
	callback, ok := p.handlerCallback[id]
	if !ok {
		return nil, fmt.Errorf("CS protocol not found id:%v", id)
	}
	return callback, nil
}

func (p *Player) checkMessage(id netpack.MessageID) error {
	switch id {
	case netpack.MessageID_CS_CREATE_CHATROOM:
	case netpack.MessageID_CS_CHAT:
	case netpack.MessageID_CS_JOIN_CHATROOM:
		if !p.isLogin() {
			return fmt.Errorf("player not login id:%v", id)
		}
	case netpack.MessageID_CS_LOGIN:
		return nil
	default:
		return fmt.Errorf("check message not found id:%v", id)
	}
	return nil
}

func (p *Player) newMessage(id netpack.MessageID) (proto.Message, error) {
	if id == netpack.MessageID_CS_LOGIN {
		return &netpack.CSLogin{}, nil
	} else if id == netpack.MessageID_CS_CREATE_CHATROOM {
		return &netpack.CSCreateChatRoom{}, nil
	} else if id == netpack.MessageID_CS_CHAT {
		return &netpack.CSChat{}, nil
	} else if id == netpack.MessageID_CS_JOIN_CHATROOM {
		return &netpack.CSJoinChatRoom{}, nil
	} else {
		return nil, fmt.Errorf("new message not found id:%v", id)
	}
}

func (p *Player) handleMessageProcess(message []byte, c *Connection) error {
	pro := &netpack.Protocol{}
	err := proto.Unmarshal(message, pro)
	if err != nil {
		return err
	}

	err = p.checkMessage(pro.Id)
	if err != nil {
		return err
	}

	msg, err := p.newMessage(pro.Id)
	if err != nil {
		return err
	}

	err = proto.Unmarshal(pro.Msg, msg)
	if err != nil {
		return err
	}

	msgCallback, err := p.getHandlerCallback(pro.Id)
	if err != nil {
		return err
	}

	err = msgCallback(msg, c)
	if err != nil {
		return err
	}
	return nil
}
